/**
*	@name							Elastic
*	@descripton						Elastic is jQuery plugin that grow and shrink your textareas automatically
*	@version						1.6.11
*	@requires						jQuery 1.2.6+
*
*	@author							Jan Jarfalk
*	@author-email					jan.jarfalk@unwrongest.com
*	@author-website					http://www.unwrongest.com
*
*	@licence						MIT License - http://www.opensource.org/licenses/mit-license.php
*/

FX.getFrame('jquery-1.3.2', function(jQuery){

    (function($){ 
        jQuery.fn.extend({  
            elastic: function() {
            
                //	We will create a div clone of the textarea
                //	by copying these attributes from the textarea to the div.
                var mimics = [
                    'paddingTop',
                    'paddingRight',
                    'paddingBottom',
                    'paddingLeft',
                    'fontSize',
                    'lineHeight',
                    'fontFamily',
                    'width',
                    'fontWeight',
                    'border-top-width',
                    'border-right-width',
                    'border-bottom-width',
                    'border-left-width',
                    'borderTopStyle',
                    'borderTopColor',
                    'borderRightStyle',
                    'borderRightColor',
                    'borderBottomStyle',
                    'borderBottomColor',
                    'borderLeftStyle',
                    'borderLeftColor'
                    ];
                
                return this.each( function() {

                    // Elastic only works on textareas
                    if ( this.type !== 'textarea' ) {
                        return false;
                    }
                        
                var $textarea	= jQuery(this),
                    $twin		= jQuery('<div />').css({
                        'position'		: 'absolute',
                        'display'		: 'none',
                        'word-wrap'		: 'break-word',
                        'white-space'	:'pre-wrap'
                    }),
                    lineHeight	= parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'),
                    minheight	= parseInt($textarea.css('height'),10) || lineHeight*3,
                    maxheight	= parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE,
                    goalheight	= 0;
                    
                    // Opera returns max-height of -1 if not set
                    if (maxheight < 0) { maxheight = Number.MAX_VALUE; }
                        
                    // Append the twin to the DOM
                    // We are going to meassure the height of this, not the textarea.
                    $twin.appendTo($textarea.parent());
                    
                    // Copy the essential styles (mimics) from the textarea to the twin
                    var i = mimics.length;
                    while(i--){
                        $twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
                    }
                    
                    // Updates the width of the twin. (solution for textareas with widths in percent)
                    function setTwinWidth(){
                        var curatedWidth = Math.floor(parseInt($textarea.width(),10));
                        if($twin.width() !== curatedWidth){
                            $twin.css({'width': curatedWidth + 'px'});
                            
                            // Update height of textarea
                            update(true);
                        }
                    }
                    
                    // Sets a given height and overflow state on the textarea
                    function setHeightAndOverflow(height, overflow){
                    
                        var curratedHeight = Math.floor(parseInt(height,10));
                        if($textarea.height() !== curratedHeight){
                            $textarea.css({'height': curratedHeight + 'px','overflow':overflow});
                        }
                    }
                    
                    // This function will update the height of the textarea if necessary 
                    function update(forced) {
                        
                        // Get curated content from the textarea.
                        var textareaContent = $textarea.val().replace(/&/g,'&amp;').replace(/ {2}/g, '&nbsp;').replace(/<|>/g, '&gt;').replace(/\n/g, '<br />');
                        
                        // Compare curated content with curated twin.
                        var twinContent = $twin.html().replace(/<br>/ig,'<br />');
                        
                        if(forced || textareaContent+'&nbsp;' !== twinContent){
                        
                            // Add an extra white space so new rows are added when you are at the end of a row.
                            $twin.html(textareaContent+'&nbsp;');
                            
                            // Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
                            if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){
                                
                                var goalheight = $twin.height()+lineHeight;
                                if(goalheight >= maxheight) {
                                    setHeightAndOverflow(maxheight,'auto');
                                } else if(goalheight <= minheight) {
                                    setHeightAndOverflow(minheight,'hidden');
                                } else {
                                    setHeightAndOverflow(goalheight,'hidden');
                                }
                                
                            }
                            
                        }
                        
                    }
                    
                    // Hide scrollbars
                    $textarea.css({'overflow':'hidden'});
                    
                    // Update textarea size on keyup, change, cut and paste
                    $textarea.bind('keyup change cut paste', function(){
                        update(); 
                    });
                    
                    // Update width of twin if browser or textarea is resized (solution for textareas with widths in percent)
                    $(window).bind('resize', setTwinWidth);
                    $textarea.bind('resize', setTwinWidth);
                    $textarea.bind('update', update);
                    
                    // Compact textarea on blur
                    $textarea.bind('blur',function(){
                        if($twin.height() < maxheight){
                            if($twin.height() > minheight) {
                                $textarea.height($twin.height());
                            } else {
                                $textarea.height(minheight);
                            }
                        }
                    });
                    
                    // And this line is to catch the browser paste event
                    $textarea.bind('input paste',function(e){ setTimeout( update, 250); });				
                    
                    // Run update once when elastic is initialized
                    update();
                    
                });
                
            } 
        }); 
    })(jQuery);
});
